﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Web;

namespace YouTubeStormer
{
    class Communications
    {
        CookieContainer cookieMonster = new CookieContainer();
        string UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3";
        ProxyInfo proxy;

        public class ProxyInfo
        {
            public string IP { get; set; }
            public string Port { get; set; }
            public string Username { get; set; }
            public string Password { get; set; }
        }

        public Communications(ProxyInfo proxy)
        {
            this.proxy = proxy;

            System.Net.ServicePointManager.ServerCertificateValidationCallback += delegate(object sender,
                System.Security.Cryptography.X509Certificates.X509Certificate certificate,
                System.Security.Cryptography.X509Certificates.X509Chain chain,
                System.Net.Security.SslPolicyErrors sslPolicyErrors)
            { return true; };
        }

        WebProxy GetProxy()
        {
            if (proxy == null) return new WebProxy();
            var webProxy = new WebProxy(proxy.IP, int.Parse(proxy.Port));
            webProxy.Credentials = new NetworkCredential(proxy.Username, proxy.Password);
            return webProxy;
        }

        HttpWebRequest PrepareWebRequest(string url, string referer = "", string host = "", string accept = "", bool allowRedirects = false)
        {
            var request = HttpWebRequest.Create(url) as HttpWebRequest;
            request.CookieContainer = cookieMonster;
            request.UserAgent = UserAgent;
            request.AllowAutoRedirect = allowRedirects;
            request.Proxy = GetProxy();
            if (referer != "") request.Referer = referer;
            if (host != "") request.Host = host;
            if (accept != "") request.Accept = accept;
            return request;
        }

        public Stream PerformGetWithStream(string url, out WebResponse streamToClose, string referer = "", string host = "", string accept = "")
        {
            var request = PrepareWebRequest(url, referer, host, accept);
            request.Method = "GET";

            try
            {
                var response = request.GetResponse();
                streamToClose = response;
                (response as HttpWebResponse).Cookies = cookieMonster.GetCookies(request.RequestUri);
                return response.GetResponseStream();
            }
            catch (Exception ex)
            {
                var a = ex;
            }
            streamToClose = null;
            return null;
        }

        public byte[] StreamToByteArray(Stream stream)
        {
            try
            {
                byte[] buffer = new byte[32768];
                using (MemoryStream ms = new MemoryStream())
                {
                    while (true)
                    {
                        int read = stream.Read(buffer, 0, buffer.Length);
                        if (read <= 0)
                            return ms.ToArray();
                        ms.Write(buffer, 0, read);
                    }
                }
            }
            catch { return null; }
        }

        public string PerformGet(string url, string referer = "", string host = "", string accept = "", bool allowRedirects = false)
        {
            var request = PrepareWebRequest(url, referer, host, accept, allowRedirects);
            request.Method = "GET";
            return ReadResponseStream(request);
        }

        public string PerformPost(string url, PostData postData, string referer = "")
        {
            try
            {
                var request = PrepareWebRequest(url, referer);
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";

                byte[] bytes = Encoding.ASCII.GetBytes(postData.ToString());
                request.ContentLength = bytes.Length;
                request.GetRequestStream().Write(bytes, 0, bytes.Length);

                return ReadResponseStream(request);
            }
            catch
            {
                return "";
            }
        }

        string ReadResponseStream(HttpWebRequest request)
        {
            try
            {
                var response = request.GetResponse();
                var cookies = cookieMonster.GetCookies(request.RequestUri);
                (response as HttpWebResponse).Cookies = cookies;
                var responseStream = response.GetResponseStream();
                var streamReader = new StreamReader(responseStream);
                var readValue = streamReader.ReadToEnd();

                response.Close();
                responseStream.Close();
                streamReader.Close();

                return readValue;
            }
            catch
            {
                return "";
            }
        }

        public class PostData
        {
            private Dictionary<string, string> Values = new Dictionary<string, string>();

            public void AddValue(string key, string value)
            {
                Values.Add(key, HttpUtility.UrlEncode(value));
            }

            public override string ToString()
            {
                if (Values.Count == 0) return "";

                List<string> values = new List<string>();
                foreach (KeyValuePair<string, string> pair in Values)
                {
                    values.Add(pair.Key + "=" + pair.Value);
                }
                return string.Join("&", values.ToArray());
            }
        }

    }
}
